package com.ptl.bp.dto;

import com.ptl.bp.config.DataAccessEnum;
import com.ptl.bp.config.SensitiveData;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

import javax.validation.constraints.*;
import java.net.URI;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 电池性能与耐久性实体类
 * 描述：包含电池技术属性和电池状态信息
 */
@Data
@Schema(description = "电池性能和耐久性数据模型")
public class BatteryPerformanceAndDurability {

    // 电池组件枚举
    public enum BatteryComponent {
        @Schema(description = "电池包") pack,
        @Schema(description = "电池模块") module,
        @Schema(description = "电池单元") cell
    }

    // 功率能力信息
    @Data
    @Schema(description = "功率能力信息")
    public static class PowerCapability {
        @DecimalMin(value = "0", message = "SoC值不能为负数")
        @Schema(description = "在特定SoC下的功率能力", required = true)
        private Double atSoC;

        @DecimalMin(value = "0", message = "功率能力值不能为负数")
        @Schema(description = "在指定SoC下的功率能力值", required = true)
        private Double powerCapabilityAt;
    }

    // 内部电阻信息
    @Data
    @Schema(description = "内部电阻信息")
    public static class InternalResistance {
        @DecimalMin(value = "0", message = "欧姆电阻值不能为负数")
        @Schema(
            description = "初始（使用前）电池包级别的内部电阻。内部电阻的定义应不同于法规定义",
            required = true
        )
        private Double ohmicResistance;

        @NotNull(message = "电池组件类型不能为空")
        @Schema(description = "电池组件类型", required = true)
        private BatteryComponent batteryComponent;
    }

    // 温度条件信息
    @Data
    @Schema(description = "温度条件信息")
    public static class TemperatureConditions {
        @DecimalMin(value = "0", message = "极端高温时间不能为负数")
        @Schema(description = "在给定温度上限以上累积的时间", required = true)
        private Double timeExtremeHighTemp;

        @DecimalMin(value = "0", message = "极端低温时间不能为负数")
        @Schema(description = "在给定温度下限以下累积的时间", required = true)
        private Double timeExtremeLowTemp;

        @DecimalMin(value = "0", message = "充电时极端高温时间不能为负数")
        @Schema(description = "充电时在给定温度上限以上累积的时间", required = true)
        private Double timeExtremeHighTempCharging;

        @DecimalMin(value = "0", message = "充电时极端低温时间不能为负数")
        @Schema(description = "充电时在给定温度下限以下累积的时间", required = true)
        private Double timeExtremeLowTempCharging;

        @NotNull(message = "最后更新时间不能为空")
        @Schema(description = "动态数据属性的最后更新时间", required = true, example = "2025-01-01 10:10:10")
        private LocalDateTime lastUpdate;
    }

    // 负事件信息
    @Data
    @Schema(description = "负事件信息")
    public static class NegativeEvent {
        @NotBlank(message = "负事件描述不能为空")
        @Schema(description = "负事件描述", required = true)
        private String negativeEvent;

        @NotNull(message = "最后更新时间不能为空")
        @Schema(description = "动态数据属性的最后更新时间", required = true, example = "2025-01-01 10:10:10")
        private LocalDateTime lastUpdate;
    }

    // 动态数值信息
    @Data
    @Schema(description = "动态数值信息")
    public static class DynamicValue<T> {
        @NotNull(message = "数值不能为空")
        @Schema(description = "数值", required = true)
        private T value;

        @NotNull(message = "最后更新时间不能为空")
        @Schema(description = "动态数据属性的最后更新时间", required = true, example = "2025-01-01 10:10:10")
        private LocalDateTime lastUpdate;
    }

    // 电池技术属性
    @Data
    @Schema(description = "电池技术属性")
    public static class TechnicalProperties {
        @NotEmpty(message = "原始功率能力不能为空")
        @Schema(
            description = "使用前的功率能力：电池法规中给出的功率能力定义。附件IV B部分第4点->要求在80%和20% SoC下测量",
            required = true
        )
        private List<PowerCapability> originalPowerCapability;

        @DecimalMin(value = "0", message = "额定最大功率不能为负数")
        @Schema(
            description = "描述电池额定最大功率值，反映功率限制相关数据",
            required = true
        )
        private Double ratedMaximumPower;

        @DecimalMin(value = "0", message = "功率能力比不能为负数")
        @Schema(
            description = "提供关于标称/推荐充电率（C-rate）的信息；等同于法规定义",
            required = true
        )
        private Double powerCapabilityRatio;

        @DecimalMin(value = "0", message = "额定能量不能为负数")
        @Schema(
            description = "根据车辆认证过程中确定的UN GTR No 22程序，认证可用的电池能量是可用的电池能量",
            required = true
        )
        private Double ratedEnergy;

        @Schema(
            description = "以周期表示的预期电池寿命。周期寿命测试的测量条件（如C-rate）和周期寿命测试中的放电深度应定义此数据属性",
            required = true
        )
        private Long expectedNumberOfCycles;

        @DecimalMin(value = "0", message = "初始自放电率不能为负数")
        @Schema(
            description = "作为使用前指标的初始自放电率（容量百分比/单位时间），在定义条件下（温度范围等）",
            required = true
        )
        private Double initialSelfDischarge;

        @DecimalMin(value = "0", message = "往返效率不能为负数")
        @DecimalMax(value = "100", message = "往返效率不能超过100%")
        @Schema(
            description = "能量往返效率是在标准充电（参见BattReg附件IV(6)）下，电池在放电测试期间提供的净能量与恢复初始充电状态所需的总能量之比",
            required = true
        )
        private Double roundtripEfficiency;

        @DecimalMin(value = "0", message = "额定容量不能为负数")
        @Schema(
            description = "额定容量是在参考条件下可以从充满电的电池中提取的总安培小时数（Ah）（参见BattReg附件IV(1)）",
            required = true
        )
        private Double ratedCapacity;

        @NotEmpty(message = "初始内部电阻不能为空")
        @Schema(
            description = "电池护照可以包含关于电池模块级别的初始内部电阻的附加信息（如果可用）。它应该与上述电池包级别要求类似地定义和计算",
            required = true
        )
        private List<InternalResistance> initialInternalResistance;

        @DecimalMin(value = "0", message = "预期寿命不能为负数")
        @Schema(
            description = "电池护照必须包含以日历年为单位的预期电池寿命信息。更新间隔必须在投放市场时和电池状态变化时",
            required = true
        )
        private Integer expectedLifetime;

        @DecimalMin(value = "0", message = "C-rate不能为负数")
        @Schema(
            description = "作为非强制性数据点，电池护照应包括标称电池功率（W）与电池能量（Wh）之比。它旨在提供适用的放电和充电率（C-rate）的指示（参见BattReg附件IV B部分(2)）。更新间隔应在投放市场时和电池状态变化时",
            required = true
        )
        private Double cRate;

        @DecimalMin(value = "0", message = "标称电压不能为负数")
        @Schema(description = "电池的标称电压", required = true)
        private Double nominalVoltage;

        @DecimalMin(value = "0", message = "最小电压不能为负数")
        @Schema(description = "电池的最小电压", required = true)
        private Double minimumVoltage;

        @DecimalMin(value = "0", message = "最大电压不能为负数")
        @Schema(description = "电池的最大电压", required = true)
        private Double maximumVoltage;

        @DecimalMin(value = "0", message = "容量耗尽阈值不能为负数")
        @DecimalMax(value = "100", message = "容量耗尽阈值不能超过100%")
        @Schema(
            description = "SOCE的百分比，在此之上电池仍被视为在其当前寿命中作为电动汽车电池运行，由经济运营商提供",
            required = true
        )
        private Double capacityThresholdForExhaustion;

        @NotNull(message = "寿命参考测试不能为空")
        @Schema(
            description = "如\"预期寿命：充放电循环次数\"中提到的非循环应用的例外也应适用于此数据属性",
            required = true,
            format = "uri"
        )
        private String lifetimeReferenceTest;

        @DecimalMin(value = "0", message = "生命周期测试C-rate不能为负数")
        @Schema(
            description = "C-rate应单独提供电池的充电和放电（如果适用）。如\"预期寿命：充放电循环次数\"中提到的非循环应用的例外也应适用于此数据属性",
            required = true
        )
        private Double cRateLifeCycleTest;

        @DecimalMin(value = "-20", message = "温度范围不能低于-20")
        @DecimalMax(value = "60", message = "温度范围不能超过60")
        @Schema(
            description = "电池可以安全承受的环境温度范围的上限和下限",
            required = true
        )
        private Double temperatureRangeIdleState;
    }

    // 电池状态信息
    @Data
    @Schema(description = "电池状态信息")
    public static class Condition {
        @DecimalMin(value = "0", message = "能量吞吐量不能为负数")
        @Schema(
            description = "应报告测量值作为进一步潜在处理的数据属性。此外，通过容量归一化可以增加一个确保电池尺寸间可比性的有用值",
            required = true
        )
        private Double energyThroughput;

        @NotNull(message = "容量吞吐量不能为空")
        @Schema(
            description = "容量吞吐量。应报告测量值作为进一步潜在处理的数据属性。此外，通过容量归一化可以增加一个确保电池尺寸间可比性的有用值",
            required = true
        )
        private DynamicValue<Double> capacityThroughput;

        @NotNull(message = "完整循环次数不能为空")
        @Schema(
            description = "充放电循环次数信息。应报告测量值作为进一步潜在处理的数据属性",
            required = true
        )
        private DynamicValue<Long> numberOfFullCycles;

        @NotNull(message = "认证能量状态不能为空")
        @Schema(
            description = "基于UNECE GTR 22的定义：在其寿命特定点测量的或车载UBE性能，表示为认证可用电池能量的百分比",
            required = true
        )
        private DynamicValue<Double> stateOfCertifiedEnergy;

        @NotNull(message = "容量衰减不能为空")
        @Schema(
            description = "容量衰减是\"随时间和使用而减少的电池在额定电压下可以提供的电荷量，相对于原始额定容量\"（参见BattReg附件IV(2)），由制造商声明",
            required = true
        )
        private DynamicValue<Double> capacityFade;

        @SensitiveData(hasAnyRole = DataAccessEnum.RIGHT)
        @NotNull(message = "剩余能量不能为空")
        @Schema(
            description = "来自UNECE GTR 22的定义，仅适用于EV。从认证使用的测试程序开始到认证使用的测试程序的适用中断标准达到为止，电池提供的能量",
            required = true
        )
        private DynamicValue<Double> remainingEnergy;

        @NotNull(message = "剩余容量不能为空")
        @Schema(
            description = "与额定容量定义相对应的使用中容量数据属性",
            required = true
        )
        private DynamicValue<Double> remainingCapacity;

        @NotEmpty(message = "负事件列表不能为空")
        @Schema(description = "负事件列表", required = true)
        private List<NegativeEvent> negativeEvents;

        @NotNull(message = "温度信息不能为空")
        @Schema(
            description = "电池护照必须包含定期记录的操作环境条件信息，包括温度",
            required = true
        )
        private TemperatureConditions temperatureInformation;

        @SensitiveData(hasAnyRole = DataAccessEnum.RIGHT)
        @NotEmpty(message = "剩余功率能力不能为空")
        @Schema(
            description = "原始功率能力（以瓦特为单位）和限制，在相关时包括温度范围。电池在参考条件下在给定时间段内能够提供的能量量。在80%和20%充电状态下的功率能力",
            required = true
        )
        private List<PowerCapability> remainingPowerCapability;

        @DecimalMin(value = "0", message = "功率衰减不能为负数")
        @Schema(
            description = "功率衰减（%）是指随时间和使用而减少的电池在额定电压下可以提供的功率量（参见BattReg附件IV(4)）。应使用原始和剩余功率能力计算功率衰减",
            required = true
        )
        private Double powerFade;

        @DecimalMin(value = "0", message = "往返效率衰减不能为负数")
        @Schema(
            description = "应使用初始往返能量效率和剩余往返能量效率计算能量往返效率衰减",
            required = true
        )
        private Double roundTripEfficiencyFade;

        @DecimalMin(value = "0", message = "自放电演变不能为负数")
        @Schema(
            description = "自放电率随时间和使用而变化，作为从初始和当前自放电率计算的百分比",
            required = true
        )
        private Double evolutionOfSelfDischarge;

        @NotNull(message = "当前自放电率不能为空")
        @Schema(
            description = "当前自放电率是在参考条件（温度等）下电池空闲状态下自放电率的变化，在老化参数x处，例如在一定存储时间或循环次数后",
            required = true
        )
        private DynamicValue<Double> currentSelfDischargingRate;

        @NotEmpty(message = "内部电阻增加不能为空")
        @Schema(
            description = "随时间和使用而增加的内部电阻应基于当前和初始值的比率定义。电池护照可以包含关于电池单元和电池模块级别的内部电阻增加的附加信息（如果可用）。它应该与上述电池包级别要求类似地定义和计算",
            required = true
        )
        private List<InternalResistance> internalResistanceIncrease;

        @DecimalMin(value = "0", message = "50%循环寿命时的往返效率不能为负数")
        @Schema(
            description = "初始往返能量效率应在参考条件下测量，包括\"50%循环寿命\"的规格。测试方法和参考条件应单独考虑非循环应用和具有非常长循环寿命的电池",
            required = true
        )
        private Double roundTripEfficiencyat50PerCentCycleLife;

        @NotNull(message = "剩余往返能量效率不能为空")
        @Schema(
            description = "电池护照应包括关于剩余往返能量效率的信息（如可能），作为电池健康状态的信息。剩余往返能量效率的更新频率应与往返能量效率衰减的更新频率一致，并应在电池状态变化时提供",
            required = true
        )
        private DynamicValue<Double> remainingRoundTripEnergyEfficiency;

        @NotNull(message = "充电状态不能为空")
        @Schema(
            description = "电池护照联盟建议将定义更改为：\"电池中可用容量表示为剩余容量的百分比\"，以反映SoC在实践中的使用",
            required = true
        )
        private DynamicValue<Double> stateOfCharge;
    }

    @NotNull(message = "电池技术属性不能为空")
    @Schema(description = "此属性涵盖所有性能相关属性", required = true)
    private TechnicalProperties batteryTechicalProperties;

    @NotNull(message = "电池状态不能为空")
    @Schema(description = "以周期表示的预期电池寿命，以及使用的参考测试。它们在设计参考条件下的预期寿命，以周期（非循环应用除外）和日历年表示",required = true )
    private Condition batteryCondition;
}